#pragma once

#include <Common/Common.h>
#include <WebSocket/WebSocketConnector.h>
#include <jsoncpp/json.h>
#include <functional>
#include <string>
using namespace std;

namespace CONFIGCENTER
{
    static const string KEY_CONTENT_TYPE = "content_type";
    static const string KEY_METHOD = "method";
    static const string KEY_UUID = "uuid";
    static const string KEY_MODTYPE = "mod_type";
    static const string KEY_RESULT = "result";
    static const string KEY_MSG = "msg";
    static const string KEY_TIMEOUT = "timeout";
    static const string KEY_CONFIG = "config";

    static const string METHOD_REGISTER = "register";
    static const string METHOD_REGISTER_ACK = "register_ack";
    static const string METHOD_GET_CONFIG = "get_config";
    static const string METHOD_GET_CONFIG_ACK = "get_config_ack";
    static const string METHOD_HEARTBEAT = "heartbeat";
    static const string METHOD_HEARTBEAT_ACK = "heartbeat_ack";
    static const string METHOD_CONFIG_CHANGED = "config_changed";
    static const string METHOD_CONFIG_CHANGED_ACK = "config_changed_ack";
}

enum ConfigCenterState
{
    HandShake,
    Registering,
    RegisterCompleted,
    Finished
};

struct ConfigCenterClientCallback
{
    std::function<void(const string &strConf)>  OnGetConfigAck;
    std::function<void(const string &strConf)>  OnConfigChanged;
    std::function<void(Int32 nError)>           OnConfigCenterError;
};

class CConfigCenterClient : public IWebSocketConnectorCallback,
                            public IWebSocketHandler,
                            public ITimerEvent,
                            public CReference
{
public:
    CConfigCenterClient(CEventEngine* pEngine);

private:
    virtual ~CConfigCenterClient();

public:
    Bool Initialize(const string &strRequst, Int32 nTimeout, const string &strUuid, const string &strModType,
        const ConfigCenterClientCallback &fnCallback);

protected:
    // IWebSocketConnectorCallback
    virtual IWebSocketHandler* OnWebSocketConnected(CWebSocketProxyPtr spProxy);
    virtual void OnWebSocketConnectError(Int32 nError);

    // IWebSocketHandler
    virtual void OnWebSocketMessage(CWebSocketProxyPtr spProxy, Bool bFin, EWebSocketOpCode eOpCode, const string &strContent);
    virtual void OnWebSocketClosed(CWebSocketProxyPtr spProxy);

    // ITimerEvent
    virtual void OnTimer(CTimer *pTimer) override;

protected:
    string ParseElementString(const Json::Value &root, const string &strField);
    Int32 ParseElementInt32(const Json::Value &root, const string &strField);
    Bool Parse(const string &strContent);

    void SendMsg(CWebSocketProxyPtr spProxy, const string &strMethod);

protected:
    CEventEngine*                               m_pEngine;
    ConfigCenterClientCallback                  m_fnConfCenterCallback;

    CWebSocketConnector                         m_connector;

    CWebSocketProxyPtr                          m_spProxy;

    CTimer*                                     m_pTimer;

	string                                      m_strUuid;
	string                                      m_strModType;

    
	string                                      m_strMethod;
    Int32                                       m_nResult;
    string                                      m_strMsg;
    Int32                                       m_nTimeout;
    string                                      m_strConfig;

	Int64										m_lHeartbeatTime;

    ConfigCenterState                           m_eState;
};
